{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 数据预处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/malele/anaconda3/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
      "  from ._conv import register_converters as _register_converters\n",
      "Using TensorFlow backend.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "X_train shape: (3827, 200, 6, 1)\n",
      "Y_train shape: (3827, 16)\n",
      "X_test shape: (957, 200, 6, 1)\n",
      "Y_test shape: (957, 16)\n"
     ]
    }
   ],
   "source": [
    "import h5py\n",
    "import numpy as np\n",
    "import tensorflow as tf \n",
    "import keras\n",
    "from keras.layers import Input, Dense, Dropout, Activation, BatchNormalization,concatenate, Flatten, Conv2D, AveragePooling2D, MaxPooling2D\n",
    "from keras.models import Model\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "def convert_to_one_hot(Y, C):\n",
    "    Y = np.eye(C)[Y.reshape(-1)].T\n",
    "    return Y\n",
    "\n",
    "file = h5py.File('DB3//DB3_S1_image.h5','r')\n",
    "imageData   = file['imageData'][:]\n",
    "imageData   = imageData*2000\n",
    "imageLabel  = file['imageLabel'][:]  \n",
    "file.close()\n",
    "\n",
    "# 随机打乱数据和标签\n",
    "N = imageData.shape[0]\n",
    "index = np.random.permutation(N)\n",
    "data  = imageData[index,:,:]\n",
    "label = imageLabel[index]\n",
    "\n",
    "# 对数据升维,标签one-hot\n",
    "data  = np.expand_dims(data, axis=3)\n",
    "label = convert_to_one_hot(label,16).T\n",
    "\n",
    "# 划分数据集\n",
    "N = data.shape[0]\n",
    "num_train = round(N*0.8)\n",
    "X_train = data[0:num_train,:,:,:]\n",
    "Y_train = label[0:num_train,:]\n",
    "X_test  = data[num_train:N,:,:,:]\n",
    "Y_test  = label[num_train:N,:]\n",
    "\n",
    "print (\"X_train shape: \" + str(X_train.shape))\n",
    "print (\"Y_train shape: \" + str(Y_train.shape))\n",
    "print (\"X_test shape: \" + str(X_test.shape))\n",
    "print (\"Y_test shape: \" + str(Y_test.shape))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "#写一个LossHistory类，保存loss和acc\n",
    "class LossHistory(keras.callbacks.Callback):\n",
    "    def on_train_begin(self, logs={}):\n",
    "        self.losses = {'batch':[], 'epoch':[]}\n",
    "        self.accuracy = {'batch':[], 'epoch':[]}\n",
    "        self.val_loss = {'batch':[], 'epoch':[]}\n",
    "        self.val_acc = {'batch':[], 'epoch':[]}\n",
    "\n",
    "    def on_batch_end(self, batch, logs={}):\n",
    "        self.losses['batch'].append(logs.get('loss'))\n",
    "        self.accuracy['batch'].append(logs.get('acc'))\n",
    "        self.val_loss['batch'].append(logs.get('val_loss'))\n",
    "        self.val_acc['batch'].append(logs.get('val_acc'))\n",
    "\n",
    "    def on_epoch_end(self, batch, logs={}):\n",
    "        self.losses['epoch'].append(logs.get('loss'))\n",
    "        self.accuracy['epoch'].append(logs.get('acc'))\n",
    "        self.val_loss['epoch'].append(logs.get('val_loss'))\n",
    "        self.val_acc['epoch'].append(logs.get('val_acc'))\n",
    "\n",
    "    def loss_plot(self, loss_type):\n",
    "        iters = range(len(self.losses[loss_type]))\n",
    "        plt.figure()\n",
    "        # acc\n",
    "        plt.plot(iters, self.accuracy[loss_type], 'r', label='train acc')\n",
    "        # loss\n",
    "        plt.plot(iters, self.losses[loss_type], 'g', label='train loss')\n",
    "        if loss_type == 'epoch':\n",
    "            # val_acc\n",
    "            plt.plot(iters, self.val_acc[loss_type], 'b', label='val acc')\n",
    "            # val_loss\n",
    "            plt.plot(iters, self.val_loss[loss_type], 'k', label='val loss')\n",
    "        plt.grid(True)\n",
    "        plt.xlabel(loss_type)\n",
    "        plt.ylabel('acc-loss')\n",
    "        plt.legend(loc=\"upper right\")\n",
    "        plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 建立模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "input_1 (InputLayer)         (None, 200, 6, 1)         0         \n",
      "_________________________________________________________________\n",
      "conv2d_1 (Conv2D)            (None, 200, 6, 32)        1952      \n",
      "_________________________________________________________________\n",
      "max_pooling2d_1 (MaxPooling2 (None, 10, 6, 32)         0         \n",
      "_________________________________________________________________\n",
      "conv2d_2 (Conv2D)            (None, 10, 6, 64)         18496     \n",
      "_________________________________________________________________\n",
      "max_pooling2d_2 (MaxPooling2 (None, 5, 6, 64)          0         \n",
      "_________________________________________________________________\n",
      "conv2d_3 (Conv2D)            (None, 3, 4, 128)         73856     \n",
      "_________________________________________________________________\n",
      "flatten (Flatten)            (None, 1536)              0         \n",
      "_________________________________________________________________\n",
      "dropout_1 (Dropout)          (None, 1536)              0         \n",
      "_________________________________________________________________\n",
      "dense_1 (Dense)              (None, 128)               196736    \n",
      "_________________________________________________________________\n",
      "dropout_2 (Dropout)          (None, 128)               0         \n",
      "_________________________________________________________________\n",
      "dense_2 (Dense)              (None, 16)                2064      \n",
      "=================================================================\n",
      "Total params: 293,104\n",
      "Trainable params: 293,104\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "def CNN(input_shape=(200,6,1), classes=16): \n",
    "    X_input = Input(input_shape)\n",
    "    \n",
    "    X = Conv2D(filters=32, kernel_size=(20,3), strides=(1,1), activation='relu', padding='same')(X_input)\n",
    "    X = MaxPooling2D((20,1))(X)\n",
    "\n",
    "    X = Conv2D(filters=64, kernel_size=(3,3), strides=(1,1), activation='relu', padding='same')(X)\n",
    "    X = MaxPooling2D((2,1))(X)\n",
    "    \n",
    "    X = Conv2D(filters=128, kernel_size=(3,3), strides=(1,1), activation='relu',padding='valid')(X)\n",
    "    \n",
    "    X = Flatten(name='flatten')(X)\n",
    "    X = Dropout(0.5)(X)\n",
    "    X = Dense(128,activation='relu')(X)\n",
    "    X = Dropout(0.5)(X)\n",
    "    X = Dense(classes, activation='softmax')(X)\n",
    "    model = Model(inputs=X_input, outputs=X)\n",
    "    return model\n",
    "    \n",
    "model = CNN()\n",
    "model.summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 训练原始数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 3827 samples, validate on 957 samples\n",
      "Epoch 1/100\n",
      "3827/3827 [==============================] - 4s 920us/step - loss: 2.3634 - acc: 0.1897 - val_loss: 1.5449 - val_acc: 0.4389\n",
      "Epoch 2/100\n",
      "3827/3827 [==============================] - 3s 813us/step - loss: 1.4834 - acc: 0.4769 - val_loss: 1.0238 - val_acc: 0.6855\n",
      "Epoch 3/100\n",
      "3827/3827 [==============================] - 3s 775us/step - loss: 1.1063 - acc: 0.5986 - val_loss: 0.7561 - val_acc: 0.7419\n",
      "Epoch 4/100\n",
      "3827/3827 [==============================] - 3s 792us/step - loss: 0.8938 - acc: 0.6807 - val_loss: 0.6090 - val_acc: 0.7806\n",
      "Epoch 5/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.7320 - acc: 0.7327 - val_loss: 0.5014 - val_acc: 0.8245\n",
      "Epoch 6/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.6317 - acc: 0.7682 - val_loss: 0.4471 - val_acc: 0.8422\n",
      "Epoch 7/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.5528 - acc: 0.8011 - val_loss: 0.4170 - val_acc: 0.8359\n",
      "Epoch 8/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.4896 - acc: 0.8257 - val_loss: 0.4293 - val_acc: 0.8433\n",
      "Epoch 9/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.4713 - acc: 0.8241 - val_loss: 0.3556 - val_acc: 0.8777\n",
      "Epoch 10/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.4262 - acc: 0.8453 - val_loss: 0.3238 - val_acc: 0.8746\n",
      "Epoch 11/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.3939 - acc: 0.8508 - val_loss: 0.3736 - val_acc: 0.8589\n",
      "Epoch 12/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.3654 - acc: 0.8646 - val_loss: 0.3256 - val_acc: 0.8589\n",
      "Epoch 13/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.3652 - acc: 0.8662 - val_loss: 0.2792 - val_acc: 0.8934\n",
      "Epoch 14/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.3289 - acc: 0.8808 - val_loss: 0.2859 - val_acc: 0.8840\n",
      "Epoch 15/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.3394 - acc: 0.8675 - val_loss: 0.2826 - val_acc: 0.8913\n",
      "Epoch 16/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.3217 - acc: 0.8759 - val_loss: 0.2589 - val_acc: 0.8945\n",
      "Epoch 17/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.2830 - acc: 0.8905 - val_loss: 0.2733 - val_acc: 0.9039\n",
      "Epoch 18/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.2756 - acc: 0.8929 - val_loss: 0.2550 - val_acc: 0.8955\n",
      "Epoch 19/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.2977 - acc: 0.8879 - val_loss: 0.2547 - val_acc: 0.9060\n",
      "Epoch 20/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.2510 - acc: 0.9012 - val_loss: 0.2499 - val_acc: 0.9018\n",
      "Epoch 21/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.2463 - acc: 0.9036 - val_loss: 0.2657 - val_acc: 0.8955\n",
      "Epoch 22/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.2406 - acc: 0.9046 - val_loss: 0.2624 - val_acc: 0.8945\n",
      "Epoch 23/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.2395 - acc: 0.9033 - val_loss: 0.2928 - val_acc: 0.8788\n",
      "Epoch 24/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.2491 - acc: 0.9093 - val_loss: 0.2451 - val_acc: 0.9070\n",
      "Epoch 25/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.2094 - acc: 0.9187 - val_loss: 0.2333 - val_acc: 0.9154\n",
      "Epoch 26/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.2260 - acc: 0.9085 - val_loss: 0.2323 - val_acc: 0.9091\n",
      "Epoch 27/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.2064 - acc: 0.9161 - val_loss: 0.2642 - val_acc: 0.9018\n",
      "Epoch 28/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.2149 - acc: 0.9085 - val_loss: 0.2539 - val_acc: 0.9060\n",
      "Epoch 29/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.2012 - acc: 0.9130 - val_loss: 0.2457 - val_acc: 0.9133\n",
      "Epoch 30/100\n",
      "3827/3827 [==============================] - 5s 1ms/step - loss: 0.2063 - acc: 0.9190 - val_loss: 0.2662 - val_acc: 0.8976\n",
      "Epoch 31/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1901 - acc: 0.9250 - val_loss: 0.2556 - val_acc: 0.9007\n",
      "Epoch 32/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.2096 - acc: 0.9211 - val_loss: 0.2746 - val_acc: 0.9039\n",
      "Epoch 33/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1860 - acc: 0.9229 - val_loss: 0.2649 - val_acc: 0.9101\n",
      "Epoch 34/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1865 - acc: 0.9305 - val_loss: 0.2442 - val_acc: 0.9091\n",
      "Epoch 35/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1833 - acc: 0.9279 - val_loss: 0.2536 - val_acc: 0.9070\n",
      "Epoch 36/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1743 - acc: 0.9287 - val_loss: 0.2209 - val_acc: 0.9112\n",
      "Epoch 37/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1716 - acc: 0.9331 - val_loss: 0.2554 - val_acc: 0.9070\n",
      "Epoch 38/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1869 - acc: 0.9253 - val_loss: 0.2412 - val_acc: 0.9080\n",
      "Epoch 39/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1623 - acc: 0.9355 - val_loss: 0.2425 - val_acc: 0.9143\n",
      "Epoch 40/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1508 - acc: 0.9391 - val_loss: 0.2533 - val_acc: 0.9112\n",
      "Epoch 41/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1726 - acc: 0.9321 - val_loss: 0.2790 - val_acc: 0.9018\n",
      "Epoch 42/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1580 - acc: 0.9347 - val_loss: 0.2408 - val_acc: 0.9122\n",
      "Epoch 43/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1593 - acc: 0.9365 - val_loss: 0.2631 - val_acc: 0.9175\n",
      "Epoch 44/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1456 - acc: 0.9430 - val_loss: 0.2386 - val_acc: 0.9206\n",
      "Epoch 45/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1368 - acc: 0.9456 - val_loss: 0.2545 - val_acc: 0.9143\n",
      "Epoch 46/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1407 - acc: 0.9425 - val_loss: 0.2743 - val_acc: 0.9080\n",
      "Epoch 47/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1411 - acc: 0.9446 - val_loss: 0.2960 - val_acc: 0.9080\n",
      "Epoch 48/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1355 - acc: 0.9483 - val_loss: 0.2525 - val_acc: 0.9195\n",
      "Epoch 49/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1489 - acc: 0.9423 - val_loss: 0.2665 - val_acc: 0.9133\n",
      "Epoch 50/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1328 - acc: 0.9451 - val_loss: 0.2571 - val_acc: 0.9269\n",
      "Epoch 51/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1324 - acc: 0.9477 - val_loss: 0.2623 - val_acc: 0.9112\n",
      "Epoch 52/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1354 - acc: 0.9462 - val_loss: 0.2573 - val_acc: 0.9049\n",
      "Epoch 53/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1385 - acc: 0.9407 - val_loss: 0.2450 - val_acc: 0.9164\n",
      "Epoch 54/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1274 - acc: 0.9519 - val_loss: 0.2380 - val_acc: 0.9195\n",
      "Epoch 55/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1054 - acc: 0.9571 - val_loss: 0.2956 - val_acc: 0.9112\n",
      "Epoch 56/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1347 - acc: 0.9488 - val_loss: 0.2674 - val_acc: 0.9060\n",
      "Epoch 57/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1186 - acc: 0.9537 - val_loss: 0.2874 - val_acc: 0.9101\n",
      "Epoch 58/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1222 - acc: 0.9524 - val_loss: 0.2538 - val_acc: 0.9195\n",
      "Epoch 59/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1185 - acc: 0.9543 - val_loss: 0.2580 - val_acc: 0.9206\n",
      "Epoch 60/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1072 - acc: 0.9545 - val_loss: 0.2985 - val_acc: 0.9195\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 61/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1109 - acc: 0.9545 - val_loss: 0.2916 - val_acc: 0.9185\n",
      "Epoch 62/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1197 - acc: 0.9548 - val_loss: 0.2661 - val_acc: 0.9237\n",
      "Epoch 63/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1185 - acc: 0.9540 - val_loss: 0.2827 - val_acc: 0.9195\n",
      "Epoch 64/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1091 - acc: 0.9587 - val_loss: 0.2561 - val_acc: 0.9227\n",
      "Epoch 65/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1112 - acc: 0.9566 - val_loss: 0.2531 - val_acc: 0.9227\n",
      "Epoch 66/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1145 - acc: 0.9543 - val_loss: 0.2987 - val_acc: 0.9122\n",
      "Epoch 67/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1182 - acc: 0.9561 - val_loss: 0.3216 - val_acc: 0.8997\n",
      "Epoch 68/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.1000 - acc: 0.9619 - val_loss: 0.2467 - val_acc: 0.9331\n",
      "Epoch 69/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0805 - acc: 0.9684 - val_loss: 0.2744 - val_acc: 0.9216\n",
      "Epoch 70/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0879 - acc: 0.9658 - val_loss: 0.2623 - val_acc: 0.9310\n",
      "Epoch 71/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0851 - acc: 0.9689 - val_loss: 0.2710 - val_acc: 0.9237\n",
      "Epoch 72/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0819 - acc: 0.9679 - val_loss: 0.2675 - val_acc: 0.9227\n",
      "Epoch 73/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0725 - acc: 0.9700 - val_loss: 0.3158 - val_acc: 0.9164\n",
      "Epoch 74/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0773 - acc: 0.9689 - val_loss: 0.3010 - val_acc: 0.9185\n",
      "Epoch 75/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0859 - acc: 0.9713 - val_loss: 0.3845 - val_acc: 0.9070\n",
      "Epoch 76/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0943 - acc: 0.9655 - val_loss: 0.3438 - val_acc: 0.9070\n",
      "Epoch 77/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0841 - acc: 0.9686 - val_loss: 0.3055 - val_acc: 0.9112\n",
      "Epoch 78/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0825 - acc: 0.9673 - val_loss: 0.2974 - val_acc: 0.9227\n",
      "Epoch 79/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0743 - acc: 0.9726 - val_loss: 0.4726 - val_acc: 0.8913\n",
      "Epoch 80/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0840 - acc: 0.9671 - val_loss: 0.3103 - val_acc: 0.9164\n",
      "Epoch 81/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0876 - acc: 0.9689 - val_loss: 0.2791 - val_acc: 0.9289\n",
      "Epoch 82/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0775 - acc: 0.9679 - val_loss: 0.3407 - val_acc: 0.9206\n",
      "Epoch 83/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0758 - acc: 0.9710 - val_loss: 0.3183 - val_acc: 0.9101\n",
      "Epoch 84/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0694 - acc: 0.9736 - val_loss: 0.2898 - val_acc: 0.9216\n",
      "Epoch 85/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0805 - acc: 0.9710 - val_loss: 0.3403 - val_acc: 0.9175\n",
      "Epoch 86/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0606 - acc: 0.9804 - val_loss: 0.3238 - val_acc: 0.9289\n",
      "Epoch 87/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0681 - acc: 0.9749 - val_loss: 0.3057 - val_acc: 0.9269\n",
      "Epoch 88/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0647 - acc: 0.9762 - val_loss: 0.3142 - val_acc: 0.9143\n",
      "Epoch 89/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0781 - acc: 0.9736 - val_loss: 0.3347 - val_acc: 0.9185\n",
      "Epoch 90/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0534 - acc: 0.9809 - val_loss: 0.3563 - val_acc: 0.9133\n",
      "Epoch 91/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0507 - acc: 0.9833 - val_loss: 0.3467 - val_acc: 0.9133\n",
      "Epoch 92/100\n",
      "3827/3827 [==============================] - 4s 1ms/step - loss: 0.0437 - acc: 0.9843 - val_loss: 0.3994 - val_acc: 0.9080\n",
      "Epoch 93/100\n",
      "3827/3827 [==============================] - 3s 871us/step - loss: 0.0484 - acc: 0.9835 - val_loss: 0.3738 - val_acc: 0.9206\n",
      "Epoch 94/100\n",
      "3827/3827 [==============================] - 3s 779us/step - loss: 0.0488 - acc: 0.9778 - val_loss: 0.4103 - val_acc: 0.9164\n",
      "Epoch 95/100\n",
      "3827/3827 [==============================] - 3s 776us/step - loss: 0.0570 - acc: 0.9817 - val_loss: 0.4137 - val_acc: 0.9154\n",
      "Epoch 96/100\n",
      "3827/3827 [==============================] - 3s 822us/step - loss: 0.0658 - acc: 0.9781 - val_loss: 0.3848 - val_acc: 0.9143\n",
      "Epoch 97/100\n",
      "3827/3827 [==============================] - 3s 837us/step - loss: 0.0768 - acc: 0.9754 - val_loss: 0.4096 - val_acc: 0.9143\n",
      "Epoch 98/100\n",
      "3827/3827 [==============================] - 3s 868us/step - loss: 0.0773 - acc: 0.9731 - val_loss: 0.3768 - val_acc: 0.9133\n",
      "Epoch 99/100\n",
      "3827/3827 [==============================] - 3s 907us/step - loss: 0.0800 - acc: 0.9749 - val_loss: 0.3215 - val_acc: 0.9237\n",
      "Epoch 100/100\n",
      "3827/3827 [==============================] - 3s 905us/step - loss: 0.0487 - acc: 0.9833 - val_loss: 0.3790 - val_acc: 0.9122\n",
      "3827/3827 [==============================] - 1s 215us/step\n",
      "Train Loss = 0.032275637824683096\n",
      "Train Accuracy = 0.9858897309687046\n",
      "957/957 [==============================] - 0s 193us/step\n",
      "Test Loss = 0.3789906446805444\n",
      "Test Accuracy = 0.9122257047686083\n",
      "time: 426.2629773616791\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "start = time.time()\n",
    "\n",
    "model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "history = LossHistory() # 创建一个history实例\n",
    "model.fit(X_train, Y_train, epochs=100, validation_data=(X_test, Y_test),batch_size=64,callbacks=[history])\n",
    "\n",
    "preds_train = model.evaluate(X_train, Y_train)\n",
    "print(\"Train Loss = \" + str(preds_train[0]))\n",
    "print(\"Train Accuracy = \" + str(preds_train[1]))\n",
    "\n",
    "preds_test  = model.evaluate(X_test, Y_test)\n",
    "print(\"Test Loss = \" + str(preds_test[0]))\n",
    "print(\"Test Accuracy = \" + str(preds_test[1]))\n",
    "\n",
    "end = time.time()\n",
    "print(\"time:\",end-start)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f2d1967a898>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "history.loss_plot('epoch')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  },
  "toc": {
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": "block",
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
